package com.hong.handler;

import com.hong.RpcServer;
import com.hong.ServiceInstance;
import com.hong.ServiceInvoke;
import com.hong.ServiceManager;
import com.hong.qrpc.Request;
import com.hong.qrpc.RequestHandler;
import com.hong.qrpc.Response;
import com.hong.qrpc.codec.Decoder;
import com.hong.qrpc.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @Author HQT
 * @Date 2022/8/10 9:34
 */
@Slf4j
public class NettyRequestHandler implements RequestHandler {
    private RpcServer rpcServer;

    public NettyRequestHandler(RpcServer rpcServer) {
        this.rpcServer = rpcServer;
    }

    @Override
    public void onRequest(InputStream receive, OutputStream response, int serializationType) {
        Response resp = new Response();
        Decoder decoder = rpcServer.getDecoders().get(serializationType);
        Encoder encoder = rpcServer.getEncoders().get(serializationType);
        ServiceManager serviceManager = rpcServer.getServiceManager();
        ServiceInvoke serviceInvoke = rpcServer.getServiceInvoke();
        try {
            byte[] data = IOUtils.readFully(receive, receive.available());
            Request request = decoder.decode(data, Request.class);
            log.info("get request:{}", request);
            ServiceInstance sis = serviceManager.lookUp(request);
            Object res = serviceInvoke.invoke(sis, request);
            resp.setData(res);
        } catch (Exception e) {
            log.error(e.getMessage());
            //调用失败
            resp.setStatusCode(-1);
            resp.setMessage("RpcServer got error:" + e.getClass().getName()
                    + " : " + e.getMessage());
        } finally {
            byte[] resBytes = encoder.encode(resp);
            try {
                response.write(resBytes);
                log.debug("response from server resp detail:{}", resp);
            } catch (IOException e) {
                log.warn(e.getMessage());
            }
        }
    }
}
